package org.visionlibrary.image.filters.clustering.proto.model;

import org.visionlibrary.image.geomtric.util.EqualsUtil;
import org.visionlibrary.image.geomtric.util.HashCodeUtil;

public abstract class Sample implements Clusterable<Sample>, Comparable<Sample>{	
	protected static double hQ = 12;
	protected static double sQ = 0.125;
	protected static double vQ = 0.125;
	
	public static void setHueQuantization(double value) {
		Sample.hQ = value;
	}
	
	public static void setSatQunatization(double value) {
		Sample.sQ = value;
	}
	
	public static void setValQuantization(double value) {
		Sample.vQ = value;
	}
	
	protected final int hue;
	protected final int sat;
	protected final int val;
	
	protected Sample(int hue, int sat, int val) {
		super();
		this.hue = hue;
		this.sat = sat;
		this.val = val;
	}
	
	@Override
	public abstract double distanceFrom(Sample p);
	
	public int getHue() {
		return hue;
	}

	public int getSat() {
		return sat;
	}

	public int getVal() {
		return val;
	}

	@Override
	public String toString() {
		return "{hue=" + hue + ", sat=" + sat + ", val=" + val + "}";
	}
	
	@Override
	public boolean equals(Object obj) {
		if(this == obj)
			return true;
		
		if(!(obj instanceof Sample))
			return false;
		
		Sample that = (Sample) obj;
		return EqualsUtil.areEqual(this.hue, that.hue) &&
			   EqualsUtil.areEqual(this.sat, that.sat) &&
			   EqualsUtil.areEqual(this.val, that.val);
	}
	
	@Override
	public int hashCode() {
		int result = HashCodeUtil.SEED;
		result = HashCodeUtil.hash(result, hue);
		result = HashCodeUtil.hash(result, sat);
		result = HashCodeUtil.hash(result, val);
		return result;
	}

	@Override
	public int compareTo(Sample o) {
		int hueDiff = hue - o.hue;
		if(0 == hueDiff) {
			int satDiff = sat - o.sat;
			if(0 == satDiff) {
				return (val - o.val);
			}
			
			return satDiff;
		}
		
		return hueDiff;
	}
}
